﻿<#
#=======================================================================================
# Name: SiteRolesInstallation.ps1
# Version: 0.2
# Author: Raphael Perez - raphael@rflsystems.co.uk
# Date: 10/01/2013
# Comment: This script will perform the Site Roles installation and initial configuration
# 
# Updates:
#        0.1 - Raphael Perez - 05/10/2012 - Initial Script
#        0.2 - Raphael Perez - 10/01/2013
#                      - Removed validation after creation of the SMS SITE SYSTEM
#                      - Added System Health Validator Installation
#                      - Added warning about console installation
#                      - Added option to create new IP Range Boundary and Boundary Group for DP IP Address
#                      - Added try/finally
#                      - Changed creation of the boundary group when creating ip range
#
# Usage:
#		 Option 1: powershell.exe -ExecutionPolicy Bypass .\SiteRolesInstallation.ps1 [Parameters]
#        Option 2: Open Powershell and execute .\SiteRolesInstallation.ps1 [Parameters]
#
# Parameters: (All parameters are optional, if you do not use, script will ask you to provide the information)
#        sdkserver - fqdn of the sdk server
#        servername - computer where the role will be installed
#        console - y/n - install cm console
#        appcatalogwebservicepoint - y/n - install application catalog webservice point
#        appcatalogwebsitepoint - y/n - install application catalog website point
#        organizationname - used when appcatalogwebsitepoint = 'y' - Organization Name
#        appcatalogwebservicepointname - used whe appcatalogwebservicepoint = 'n' - fqdn of the application catalog webservice point
#        aiupdateservicepoint - y/n - install asset intelligence service point
#        distributionpoint - y/n - install distribution point
#        distributionpointpxe - used when distributionpoint = 'y' - y/n - enable pxe service point
#        createdistributionpointgroup - used when distributionpoint = 'y' - y/n - create distribution point group
#        distributionpointgroup - used createdistributionpointgroup = 'y' - y/n - DP Group Name
#        createiprange - used createdistributionpointgroup = 'y'  - Create Boundary IP Range from the DP IP Address and will add to the DP Group Created
#        addDPTOBoundaryGroup - used when distributionpoint = 'y' - y/n - add the DP to the default boundary group (if it was created during installation)
#        EndpointProtectionPoint - y/n - install Endpoint Protection
#        adr - y/n - create ADR for EP Definition
#        packagelocation - package locaiton for ADR (format \\server\share\folder)
#        fallbackstatuspoint - y/n - install fallback status point
#        managementpoint - y/n - install management point
#        Softwareupdatepoint - y/n - install software update point
#        connecttoparentsite - y/n - connect to a parent site (used for primary site child and secondary sites)
#        parentsite - fqdn of the parent site
#        Statemigrationpoint - y/n - install state migraiton pint
#        Statemigrationpointfolder - state migraiton point folder
#        systemhealthvalidator - install system health validator point
#
# Examples:
#        ./SiteRolesInstallation -sdkserver 'sccm01.mylab.com' -servername 'sccm01.mylab.com' -console 'n' -appcatalogwebservicepoint 'y' -appcatalogwebsitepoint 'y' -organizationname 'My Lab Organization' -aiupdateservicepoint 'y' -distributionpoint 'y' -distributionpointpxe 'y' -createdistributionpointgroup 'y' -distributionpointgroup 'Headquarters' -createiprange 'y' -addDPTOBoundaryGroup 'y' -EndpointProtectionPoint 'y' -adr 'y' -packagelocation '\\sccm01\source$\epdef' -fallbackstatuspoint 'y' -managementpoint 'y' -Softwareupdatepoint 'y' -connecttoparentsite 'n' -Statemigrationpoint 'y' -Statemigrationpointfolder 'e:\SMP'
#        - use the sdk server SCCM01.mylab.com and install the site role to the sccm01.mylab.com server
#        - it will not install console, it will install application catalog website and webservice point with organization name My Lab Organization
#        - it will install the asset intelligence point, distribution point and enable pxe, create a DP Group Headquarters and add it to the default DP Group if exists
#        - install Endpoint Protection, create ADR and and the package location to \\sccm01\source$\epdef
#        - install fallback status point, management point, software update point (it will not connect to any other site - used as primary std site)
#        - install state migraiton point and use e:\SMP as state migration point folder
#=======================================================================================
#>
PARAM(
    $sdkserver = '',
    $servername = '',
    $console = '',
    $appcatalogwebservicepoint = '',
    $appcatalogwebsitepoint = '',
    $organizationname = '',
    $appcatalogwebservicepointname = '',
    $aiupdateservicepoint = '',
    $distributionpoint = '',
    $distributionpointpxe = '',
    $createdistributionpointgroup = '',
    $distributionpointgroup = '',
    $createiprange = '',
    $addDPTOBoundaryGroup = '',
    $EndpointProtectionPoint = '',
    $adr = '',
    $packagelocation = '',
    $fallbackstatuspoint = '',
    $managementpoint = '',
    $Softwareupdatepoint = '',
    $connecttoparentsite = '',
    $parentsite = '',
    $Statemigrationpoint = '',
    $Statemigrationpointfolder = ''
)
try
{
    $ErrorActionPreference = "Stop" 
    $logsize = 10
    $maxretry = 5
    $MediaFolder = $MediaFolder = (Get-Item (Get-Location).Path).Parent.FullName
    if ($MediaFolder -eq '') { (Get-Location).Path }
    if ($mediaFolder.substring($mediaFolder.length-1) -ne '\') { $mediaFolder += '\' }        

    if (!(Test-Path -Path .\Functions.ps1))
    {
        Write-Host "Module Functions.ps1 does not exist on the current folder, no futher action taken" -ForegroundColor Red
    }
    else
    {
        Import-Module -name .\Functions.ps1
    }
    $scriptName = ($MyInvocation.MyCommand.Name)
    $StrDateTime = Get-Date -uformat "%d%m%Y-%H%M"
    $path = $MediaFolder + "_Logs\" + ($MyInvocation.MyCommand.Name -replace '.ps1', '') + ".log"
    $component = ($MyInvocation.MyCommand.Name -replace '.ps1', '')
    New-Item ($MediaFolder + '_Logs') -type directory -force | out-null 
    try
    {
        New-Item ($MediaFolder + '_Logs\Test.log') -type file -force | out-null 
        Remove-Item ($MediaFolder + '_Logs\Test.log') -force | out-null 
    }
    catch
    {
        Write-Host "Unable to read/write file on $MediaFolder folder, no futher action taken" -ForegroundColor Red
        Exit    
    }

    [Environment]::SetEnvironmentVariable("SEE_MASK_NOZONECHECKS", "1", "Process")

    if (!(Test-IsAdmin)) { Exit }
    if (!(Test-PowerShell64)) { Exit }
    if (!(Test-IsMediaFolderExist -MediaFolder $MediaFolder)) { Exit }
    $logsize = 10
    $computerinfo = Get-WmiObject Win32_ComputerSystem
    $computerfqdn = $computerinfo.name + '.' + $computerinfo.Domain
    if ((gwmi  -namespace 'root\sms' -class 'SMS_ProviderLocation' -ErrorAction SilentlyContinue) -eq $null)
    {
        $sdkserver = (BuildAnswer -return $sdkserver -question 'SDK Server' -allowblank $false -errorMsg 'SDK Server')
        $servername = (BuildAnswer -return $servername -question 'Computer Name' -default $computerfqdn)
    }
    else
    {
        $sdkserver = (BuildAnswer -return $sdkserver -question 'SDK Server' -default $computerfqdn)
        $servername = (BuildAnswer -return $servername -question 'Computer Name' -allowblank $false -errorMsg 'Computer Name')
    }
    $sitecode = (gwmi -namespace 'root\sms' -class 'SMS_ProviderLocation' -ComputerName $sdkserver).SiteCode
    $siteinfo = gwmi -Namespace ("root\sms\site_$siteCode") -ComputerName ($sdkServer) -query ('select * from SMS_Site where SiteCode = "'+$siteCode+'"')
    $sitetype = $siteinfo.Type
    $reportingto = $siteinfo.ReportingSiteCode
    if ($reportingto -eq $null) { $reportingto = '' }

    $centralsite = (iif -question ($sitetype -eq '4') 'y' -falsevalue 'n')
    $primarysitestd = (iif -question (($sitetype -eq '2') -and ($reportingto -eq '')) 'y' -falsevalue 'n')
    $primarysitechild = (iif -question (($sitetype -eq '2') -and ($reportingto -ne '')) 'y' -falsevalue 'n')
    $secondarysite = (iif -question ($sitetype -eq '1') 'y' -falsevalue 'n')

    Write-Log -message "*if you choise to install the SCCM Console, it will be installed on this machine, even the Computer Name is a remote machine" -severity 2
    $console = (BuildAnswer -return $console -question 'Install SCCM Console?' -options "y/n" -default "n").ToLower()

    if (($centralsite -eq 'y') -or ($secondarysite -eq 'y'))
    {
        $appcatalogwebservicepoint = 'n'
        $appcatalogwebsitepoint = 'n'
    }
    else
    {
        $appcatalogwebservicepoint = (BuildAnswer -return $appcatalogwebservicepoint -question 'Install Application Catalog web service Point?' -options "y/n" -default "n").ToLower()
        $appcatalogwebsitepoint = (BuildAnswer -return $appcatalogwebsitepoint -question 'Install Application catalog website Point?' -options "y/n" -default "n").ToLower()
        if (($appcatalogwebsitepoint -eq 'y') -and ($appcatalogwebservicepoint -eq 'n'))
        {
            $appcatalogwebservicepointname = (BuildAnswer -return $appcatalogwebservicepointname -question 'Application Catalog web sevice point server FQDN name' -allowblank $false -errorMsg 'Application Catalog web service point server FQDN name')
        }
        else { $appcatalogwebservicepointname = $servername }

        if ($appcatalogwebsitepoint -eq 'y') { $organizationname = (BuildAnswer -return $organizationname -question 'Organization Name') }
    }

    if (($centralsite -eq 'y') -or ($primarysitestd -eq 'y'))
    { $aiupdateservicepoint = (BuildAnswer -return $aiupdateservicepoint -question 'Install Asset Intelligence Syncronization Point?' -options "y/n" -default "n").ToLower() }
    else { $aiupdateservicepoint = 'n' }

    if ($centralsite -eq 'y') { $distributionpoint = 'n' }
    else 
    {
        $distributionpoint = (BuildAnswer -return $distributionpoint -question 'Install Distribution Point?' -options "y/n" -default "n").ToLower()
        if ($distributionpoint -eq 'y')
        {
            New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT -ErrorAction SilentlyContinue | out-null
            $registry = $null
            for ($i = 1; $i -le $maxretry; $i++)
            {
                $registry = Get-Item "hkcr:clsid\{0ACEA30B-2CF9-4cd6-98A2-1D2A1FAE8FEE}\InprocServer32" -ErrorAction SilentlyContinue
                if ($registry -eq $null)
                {
                    Write-Log -Message "Registering tsmediaapi.dll...Starting"
                    
                    $tsmediaapi = "$mediaFolder\DLLs\tsmediaapi.dll"
                    if (Test-Path -Path $tsmediaapi)
                    {
                        Copy-Item $tsmediaapi "$env:SystemRoot\system32" -Force -ErrorAction SilentlyContinue
                        Write-Log -Message ("Commandline: $env:SystemRoot\system32\regsvr32.exe /s $env:SystemRoot\system32\tsmediaapi.dll")
                        Start-Process -Filepath ("$env:SystemRoot\system32\regsvr32.exe") -ArgumentList ("/s $env:SystemRoot\system32\tsmediaapi.dll") -wait
                    }
                    else
                    {
                        Write-Log -Message "File tsmediaapi.dll does not exist, no futher action taken" -severity 3
                        Write-Log -Message "To register the tsmediaapi.dll, download the CM12 SDK, copy the file tsmediaapi.dll from 'Redistributables\amd64' to %windir%\system32 and use regsvr32.exe to register it"
                        Exit
                    }           
                    Write-Log -Message "Registering tsmediaapi.dll...Done"
                }
                else { break }
            }
            if ($registry -eq $null)
            {
                Write-Log -Message "File tsmediaapi.dll could not be registered, no futher action taken" -severity 3
                Write-Log -Message "To register the tsmediaapi.dll, download the CM12 SDK, copy the file tsmediaapi.dll from 'Redistributables\amd64' to %windir%\system32 and use regsvr32.exe to register it"
                Exit
            }
                
            $distributionpointpxe = (BuildAnswer -return $distributionpointpxe -question 'Enable PXE Server?' -options "y/n" -default "n").ToLower()
            $createdistributionpointgroup = (BuildAnswer -return $createdistributionpointgroup -question 'Create DP Group?' -options "y/n" -default "n").ToLower()
            if ($createdistributionpointgroup -eq 'y')
            {
                $distributionpointgroup = (BuildAnswer -return $distributionpointgroup -question 'Distribution Point Group Name?' -allowblank $false -errorMsg 'Distribution Point Group Name').ToLower()
                $createiprange = (BuildAnswer -return $createiprange -question 'Create Boundary IP Range?' -options "y/n" -default "n").ToLower()
            }
            
            $addDPTOBoundaryGroup = (BuildAnswer -return $addDPTOBoundaryGroup -question 'Add Distribution Point to Default Boundary Group?' -options "y/n" -default "n").ToLower()
        }
    }

    if (($centralsite -eq 'y') -or ($primarysitestd -eq 'y'))
    {
        $EndpointProtectionPoint = (BuildAnswer -return $EndpointProtectionPoint -question 'Install Endpoint Protection Point?' -options "y/n" -default "n").ToLower()
        if ($EndpointProtectionPoint -eq 'y')
        {
            $adr = (BuildAnswer -return $adr -question 'Create Automatic Deployment Rules for Endpoint Protection?' -options "y/n" -default "n").ToLower()
            if ($adr -eq 'y')    
            {
                $packagelocation = (BuildAnswer -return $packagelocation -question 'Deployment Package Location (format: \\servername\share\folder)?'  -allowblank $false -errorMsg 'Deployment Package Location').ToLower()
            }        
        }
    }
    else { $EndpointProtectionPoint = 'n' }

    if (($centralsite -eq 'y') -or ($secondarysite -eq 'y'))
    {
        $fallbackstatuspoint = 'n'
        $managementpoint = 'n'
    }
    else
    {
        $fallbackstatuspoint = (BuildAnswer -return $fallbackstatuspoint -question 'Install Fallback Status Point?' -options "y/n" -default "n").ToLower()
        $managementpoint = (BuildAnswer -return $managementpoint -question 'Install Management Point?' -options "y/n" -default "n").ToLower()
    }

    $Softwareupdatepoint = (BuildAnswer -return $Softwareupdatepoint -question 'Install Software Update Point?' -options "y/n" -default "n").ToLower()
    if ($Softwareupdatepoint -eq 'y')
    {
        $connecttoparentsite = (BuildAnswer -return $connecttoparentsite -question 'Install a Child Software Update Point?' -options "y/n" -default "n").ToLower()
        if ($connecttoparentsite -eq 'y')
        { 
            $parentsite = (BuildAnswer -return $parentsite -question 'Parent Site Server FQDN Name?' -allowblank $false -errorMsg 'Parent Site Server FQDN Name') 
        }
        else { $parentsite = '' }
    }

    if ($centralsite -eq 'y') { $Statemigrationpoint = 'n' }
    else
    {
        $Statemigrationpoint = (BuildAnswer -return $Statemigrationpoint -question 'Install State Migration Point?' -options "y/n" -default "n").ToLower()
        if ($Statemigrationpoint -eq 'y')
        {
            $Statemigrationpointfolder = (BuildAnswer -return $Statemigrationpointfolder -question 'Folder to be used for SMP' -allowblank $false -errorMsg 'SMP Folder').ToLower()
        }
    }

    if ($secondarysite -eq 'y') { $systemhealthvalidator = 'n' }
    else
    { $systemhealthvalidator = (BuildAnswer -return $systemhealthvalidator -question 'Install System health Validator Point?' -options "y/n" -default "n").ToLower() }

    Write-Log -message "organizationname: $organizationname"
    Write-Log -message "console: $console"
    Write-Log -message "appcatalogwebservicepoint: $appcatalogwebservicepoint"
    Write-Log -message "appcatalogwebsitepoint: $appcatalogwebsitepoint"
    Write-log -message "appcatalogwebservicepointname: $appcatalogwebservicepointname"
    Write-Log -message "aiupdateservicepoint: $aiupdateservicepoint"
    Write-Log -message "distributionpoint: $distributionpoint"
    Write-Log -message "distributionpointgroup: $distributionpointgroup"
    Write-Log -message "createiprange: $createiprange"
    Write-Log -message "distributionpointpxe: $distributionpointpxe"
    Write-log -message "addDPTOBoundaryGroup: $addDPTOBoundaryGroup"
    Write-Log -message "EndpointProtectionPoint: $EndpointProtectionPoint"
    Write-Log -message "adr: $adr"
    Write-Log -message "packagelocation: $packagelocation"
    Write-Log -message "fallbackstatuspoint: $fallbackstatuspoint"
    Write-Log -message "managementpoint: $managementpoint"
    Write-Log -message "Softwareupdatepoint: $Softwareupdatepoint"
    Write-Log -message "connecttoparentsite: $connecttoparentsite"
    Write-Log -message "parentsite: $parentsite"
    Write-Log -message "Statemigrationpoint: $Statemigrationpoint"
    Write-Log -message "Statemigrationpointfolder: $Statemigrationpointfolder"
    Write-Log -message "systemhealthvalidator: $systemhealthvalidator"

    if ($console -eq 'y')
    {
        Install-SCCMConsole -MediaFolder $MediaFolder -ServerName $servername
        MDTInstallation -MediaFolder $MediaFolder 
        MDTIntegration
    }

    if (($appcatalogwebservicepoint -eq 'n') -and ($appcatalogwebsitepoint -eq 'n') -and ($aiupdateservicepoint -eq 'n') -and ($distributionpoint -eq 'n') -and ($EndpointProtectionPoint -eq 'n') -and ($fallbackstatuspoint -eq 'n') -and ($managementpoint -eq 'n') -and ($Softwareupdatepoint -eq 'n') -and ($Statemigrationpoint -eq 'n') -and ($systemhealthvalidator -eq 'n') -and ($reportingservicespoint -eq 'n'))
    {
        Write-Log -message "No option was selected, no futher action taken" -severity 3
        Exit
    }

    $sitesystem = gwmi -Namespace ("root\sms\site_$siteCode") -ComputerName ($sdkServer) -query ('select * from SMS_SCI_SysResUse where NetworkOSPath="\\\\' + $servername + '" and RoleName ="SMS Site System"')
    if ($sitesystem -eq $null)
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS SITE SYSTEM' -componentname 'SMS_EXECUTIVE' -servername $servername
    }

    if ($aiupdateservicepoint -eq 'y')
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'AI UPDATE SERVICE POINT' -componentname 'AI_UPDATE_SERVICE_POINT' -servername $servername
        Write-Log ('Extra configuration...Starting')
        $SMS_AIProxy_class = [wmiclass]""  
        $SMS_AIProxy_class.psbase.Path = "\\" + $sdkserver + "\ROOT\SMS\site_" + $SiteCode + ":SMS_AIProxy"
        
        $SMS_AIProxy = $SMS_AIProxy_class.createInstance()
        $SMS_AIProxy.PeriodicCatalogUpdateEnabled = $true;
        $SMS_AIProxy.PeriodicCatalogUpdateSchedule = "0001200000100038";
        $SMS_AIProxy.Port = 443;
        $SMS_AIProxy.ProxyCertPath = "";
        $SMS_AIProxy.ProxyEnabled = $true;
        $SMS_AIProxy.ProxyName = $servername;
        $SMS_AIProxy.SiteCode = $sitecode;    
        $SMS_AIProxy.Put() | Out-Null
        Write-Log ('Extra configuration...Done')
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'AI UPDATE SERVICE POINT' -componentname 'AI_UPDATE_SERVICE_POINT' -servername $servername
    }

    if ($fallbackstatuspoint -eq 'y')
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Fallback Status Point' -componentname 'SMS_FALLBACK_STATUS_POINT' -servername $servername
        Write-Log ('Extra configuration...Starting')
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -property 'Advanced Client Command Line' -value 0 -value1 (' FSP=' + $servername) -addvalue1 $true -componentname ('SMS_CLIENT_CONFIG_MANAGER|'+$sdkserver)
        Write-Log ('Extra configuration...Done')
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Fallback Status Point' -componentname 'SMS_FALLBACK_STATUS_POINT' -servername $servername
    }

    if ($managementpoint -eq 'y')
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Management Point' -componentname 'SMS_MP_CONTROL_MANAGER' -servername $servername
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Management Point' -componentname 'SMS_MP_CONTROL_MANAGER' -servername $servername
        
        Write-Log -message ('Testing MP Connection...Starting')
        $web = Get-ConnectToMP -servername $servername -ConnectionType 'mplist'
        if ($web.status -eq '200') 
        { Write-Log -message ('Successfully MPList Connection') }
        else { Write-Log -message ('Error retrieving MPList. HTTP Error Code: ' + $web.Status) -severity 3 }
        
        $web = Get-ConnectToMP -servername $servername -ConnectionType 'mpcert'
        if ($web.status -eq '200') 
        { Write-Log -message ('Successfully MPCert Connection') }
        else { Write-Log -message ('Error retrieving MPCert. HTTP Error Code: ' + $web.Status) -severity 3 }
        Write-Log ('Testing MP Connection...Done')
    }

    if ($distributionpoint -eq 'y') 
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Distribution Point' -componentname 'SMS_DISTRIBUTION_MANAGER' -pxe $distributionpointpxe -servername $servername
        if ($distributionpointgroup -ne '')
        {
            CreateDPGroup -sitecode $sitecode -sdkserver $sdkserver -name $distributionpointgroup -servername $servername
            
            if ($createiprange -eq 'y')
            {        
                try
                { $network = gwmi -ComputerName $servername -class win32_networkadapterconfiguration -ErrorAction SilentlyContinue | where-object { $_.IPAddress -ne $null} }
                catch { $network = $null }
                
                if ($network -ne $null)
                {
                    New-BoundaryGroup -sdkServer $sdkServer -sitecode $siteCode -Name "IP Range $distributionpointgroup" -secondary $true
                    $boundaryID = New-IPRangeBoundary -sdkServer $sdkServer -sitecode $siteCode -IPAddress ($network.IPAddress[0]) -IPSubnet ($network.IPSubnet[0]) -Description "IP Range $distributionpointgroup"
                    AssignBoundaryToBoundaryGroup -sdkServer $sdkServer -sitecode $siteCode -BoundaryGroupName "IP Range $distributionpointgroup" -BoundaryID $boundaryID
                    AddDPToBoundaryGroup -sitecode $sitecode -sdkserver $sdkserver -servername $servername -BoundaryGroupName "IP Range $distributionpointgroup"
                }
                else
                {
                    Write-Log -Message ('Ignoring creating Boundary Group/Boundary IP Range due connectivity issue with DP') -severity 2
                }
            }
        }

        if ($addDPTOBoundaryGroup -eq 'y')
        {
            AddDPToBoundaryGroup -sitecode $sitecode -sdkserver $sdkserver -servername $servername -BoundaryGroupName ($env:USERDNSDOMAIN)
        }
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Distribution Point' -componentname 'SMS_DISTRIBUTION_MANAGER' -servername $servername
    }

    if ($Statemigrationpoint -eq 'y') 
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS State Migration Point' -componentname 'SMS_STATE_MIGRATION_POINT' -folder $Statemigrationpointfolder -servername $servername
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS State Migration Point' -componentname 'SMS_STATE_MIGRATION_POINT' -servername $servername
    }

    if ($Softwareupdatepoint -eq 'y')
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Software Update Point' -componentname 'SMS_WSUS_CONTROL_MANAGER' -servername $servername
        Write-Log ('Extra configuration...Starting')
        $component = 'SMS_WSUS_CONFIGURATION_MANAGER|'+$sdkserver
        
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultWSUS' -value 0 -value2 $servername
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultWSUSType' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultPublicVIP' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultWSUSIISPort' -value 80
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultWSUSIISSSLPort' -value 443
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultWSUSAccessAccount' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'SSLDefaultWSUS' -value 0
        
        if ($reportingto -eq '')
        {
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultUseParentWSUS' -value 0
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'ParentWSUS' -value 0
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'ParentWSUSPort' -value 80
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Supersedence Mode' -value 0
        }
        else
        {
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultUseParentWSUS' -value 1
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'ParentWSUS' -value 0 -value2 $parentsite
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'ParentWSUSPort' -value 8530
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Supersedence Mode' -value 1
        }
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'DefaultIsAlsoINF' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFWSUS' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFWSUSType' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFPublicVIP' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFWSUSIISPort' -value 80
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFWSUSIISSSLPort' -value 443
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFWSUSAccessAccount' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'SSLINFWSUS' -value 1
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'INFUseParentWSUS' -value 1
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'SSLToParentWSUS' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Number of Retries' -value 100
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Retry Delay' -value 60
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'SupportedTitleLanguages' -value 0 -value2 'en'
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'SupportedUpdateLanguages' -value 0 -value2 'en'
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'SMSClientDeployment' -value 0 -value1 'Disabled'
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'RequestedClientVersion' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'MaxClientsPublished' -value 1
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'HostBinariesOnMicrosoftUpdate' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'ClientReportingLevel' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'MaximumAllowedComputers' -value 100000
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'WSUS Scan Retry Error Codes' -value 0 -value1 'REG_SZ' -value2 ('2149859372', '2149842970', '2147954429', '2149859352', '2149859362', '2149859338', '2149859344', '2147954430', '2147747475', '2149842974', '2149859342')
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Supersedence Age' -value 3

        if ($reportingto -eq '') 
        {
            $all = gwmi -Namespace ("root\sms\site_$siteCode") -computername ($sdkServer) -query ("SELECT * FROM SMS_UpdateCategoryInstance where IsSubscribed=1")
            if ($all -ne $null)
            {
                foreach ($all1 in $all)
                {
                    $all1.IsSubscribed = $false
                    $all1.Put() | Out-Null
                }
            }
            
            $ClassificationsName = "'Critical Updates','Definition Updates', 'Feature Packs','Security Updates','Service Packs','Tools','Update Rollups', 'Updates'"
            $classifications = gwmi -Namespace ("root\sms\site_$siteCode") -computername ($sdkServer) -query ("SELECT * FROM SMS_UpdateCategoryInstance where LocalizedCategoryInstanceName in ("+$ClassificationsName+")")
            if ($classifications -ne $null)
            {
                foreach ($class in $classifications)
                {
                    $class.IsSubscribed = $true
                    $class.Put() | Out-Null
                }
            }
            
            $ProductNames = "'Office 2007', 'Office 2010', 'Windows 7', 'Windows Server 2003', 'Windows Server 2008 R2', 'Windows Server 2008', 'Windows Vista', 'Windows XP 64-Bit Edition Version 2003', 'Windows XP x64 Edition', 'Windows XP'"
            $products = gwmi -Namespace ("root\sms\site_$siteCode") -ComputerName ($sdkServer) -query ("select * from SMS_UpdateCategoryInstance where (CategoryTypeName='Product' or CategoryTypeName='ProductFamily' or CategoryTypeName='Company') and AllowSubscription=1 and LocalizedCategoryInstanceName in ("+$ProductNames+")")
            if ($products -ne $null)
            {
                foreach ($prod in $products)
                {
                    $prod.IsSubscribed = $true
                    $prod.Put() | Out-Null
                }
            }
        }
        $component = 'SMS_WSUS_SYNC_MANAGER|'+$sdkserver
        
        if ($reportingto -eq '')
        {
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Schedule' -value 0 -value1 '0001200000100038'
        }
        else
        {
            ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Schedule' -value 0
        }
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Retry Interval' -value 60
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Retry Count' -value 48
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Updates Cleanup Age' -value 7
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Full Sync Interval (days)' -value 7
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'Sync Now' -value 0
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'MaxInstallTime-Update' -value 600
        ChangePropComponent -sdkServer $sdkServer -sitecode $siteCode -componentname $component -property 'MaxInstallTime-ServicePack' -value 3600
        
        Write-Log ('Extra configuration...Done')
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Software Update Point' -componentname 'SMS_WSUS_CONTROL_MANAGER' -servername $servername
    }

    if ($appcatalogwebservicepoint -eq 'y') 
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Application Web Service' -componentname 'SMS_AWEBSVC_CONTROL_MANAGER' -servername $servername
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Application Web Service' -componentname 'SMS_AWEBSVC_CONTROL_MANAGER' -servername $servername
    }

    if ($appcatalogwebsitepoint -eq 'y') 
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Portal Web Site' -componentname 'SMS_PORTALWEB_CONTROL_MANAGER' -servername $servername -organizationname $organizationname -webserviceservername $appcatalogwebservicepointname
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Portal Web Site' -componentname 'SMS_PORTALWEB_CONTROL_MANAGER' -servername $servername
    }

    if ($EndpointProtectionPoint -eq 'y')
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Endpoint Protection Point' -componentname 'SMS_ENDPOINT_PROTECTION_MANAGER' -servername $servername
        Write-Log ('Extra configuration...Starting')
        ChangePropClientComp -sdkServer $sdkServer -sitecode $siteCode -property 'LicenseAgreed' -value 1 -component 'Endpoint Protection'
        Write-Log ('Extra configuration...Done')
        
        Write-log -message ('Creating CM Device Folders...Starting')
        Add-CMFolder -sdkServer $sdkServer -sitecode $siteCode -FolderName "Endpoint Protection" -FolderType 5000
        Write-log -message ('Creating CM Device Folders...Done')
        
        Write-log -message ('Creating CM Device Collections...Starting')
        Add-CMCollection -sdkserver $sdkServer -sitecode $siteCode -type 2 -Name '[Custom] All Endpoint Protection Clients' -Folder 'Endpoint Protection' -query 'select * from SMS_R_System inner join SMS_G_System_EndpointProtectionStatus on SMS_G_System_EndpointProtectionStatus.ResourceId = SMS_R_System.ResourceId where SMS_G_System_EndpointProtectionStatus.Protected = 1'
        $cmAllClients = Get-CMCollection -sdkserver $sdkserver -sitecode $SiteCode -type 2 -name '[Custom] All Endpoint Protection Clients'
        if ($cmAllClients -ne $null)
        {
            Add-CMCollection -sdkserver $sdkServer -sitecode $siteCode -type 2 -Name '[Custom] All Endpoint Protection Domain Controllers' -Folder 'Endpoint Protection' -query 'select * from  SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_G_System_COMPUTER_SYSTEM.Roles like "%Domain_Controller%"' -LimitToCollectionID $cmAllClients.CollectionID
            Add-CMCollection -sdkserver $sdkServer -sitecode $siteCode -type 2 -Name '[Custom] All Endpoint Protection SCCM Servers' -Folder 'Endpoint Protection' -query 'select * from SMS_R_System where SMS_R_System.SystemRoles is not null' -LimitToCollectionID $cmAllClients.CollectionID
        }    
        Write-log -message ('Creating CM Device Collections...Done')
        
        if ($adr -eq 'y')
        {    
            CreateSoftwareUpdatePackage -sdkServer $sdkServer -sitecode $siteCode -packagename 'Endpoint Protection - Definition Update' -packagelocation $packagelocation
            CreateADR -sdkServer $sdkServer -sitecode $siteCode -packagename 'Endpoint Protection - Definition Update'
        }
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS Endpoint Protection Point' -componentname 'SMS_ENDPOINT_PROTECTION_MANAGER' -servername $servername
    }

    if ($systemhealthvalidator -eq 'y')
    {
        CreateSiteRole -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS System Health Validator' -componentname 'SMS_SYSTEM_HEALTH_VALIDATOR' -servername $servername
        ValidateSiteRoleInstallation -sitecode $sitecode -sdkserver $sdkserver -rolename 'SMS System Health Validator' -componentname 'SMS_SYSTEM_HEALTH_VALIDATOR' -servername $servername
    }
    Write-Log -Message ('Log size...Configuring it to '+$logsize+' MB') 
    Get-ChildItem "hklm:Software\Microsoft\SMS\Tracing" | ForEach-Object { (set-ItemProperty -path $_.psPath -name 'MaxFileSize' -value ($logsize*1024*1024)) }
    Write-Log -Message ('Log size...Done')
}
finally
{
    $module = Get-Module -name Functions | where-object {$_.ModuleType -eq "Script"}
    if ($module -ne $null) 
    { 
        if ($module.Path.ToLower() -eq ($MediaFolder.ToLower() + "scripts\functions.ps1")) { Remove-Module $module }
    }
}     